package com.learn.datainjector;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class TextInjector {

	public <T>T injector(String text,Class<T> type,String root) throws Exception{
		T obj = type.newInstance();
		TextFormat textFormat = new TextFormat();
		List<FieldData> fieldDatas = textFormat.getFieldDatas(text, root);
		Map<String, Object> fieldObjs = new HashMap<String, Object>();
		for (FieldData fieldData : fieldDatas) {
			Object useObj = obj;
			String key = fieldData.getDataKey();
			String fieldName = fieldData.getFieldName();
			String value = fieldData.getFieldVal();
			if(key!=null){
				Object fieldUseObj = fieldObjs.get(key);
				if(fieldUseObj == null){
					String[] dataKeys = fieldData.getDataKeys();
					for (String dataKey : dataKeys) {
						fieldUseObj = getFieldObject(dataKey, useObj);
						useObj = fieldUseObj;
					}
					if(fieldUseObj!=null){
						fieldObjs.put(key, fieldUseObj);
					}
				}else{
					useObj = fieldUseObj;
				}
			}
			setFieldObject(fieldName, value, useObj);
		}
		return obj;
	}
	public void setFieldObject(String name,String value,Object useObj){
		if(useObj == null){
			return;
		}
		try {
			Field field = useObj.getClass().getDeclaredField(name);
			field.setAccessible(true);
			Class type = field.getType();
			Object val = value;
			
			if(type==int.class||type==Integer.class){
				val = Integer.parseInt(value);
			}else if(type==long.class||type==Long.class){
				val = Long.parseLong(value);
			}else if(type==short.class||type==short.class){
				val = Short.parseShort(value);
			}else if(type==double.class||type==Double.class){
				val = Double.parseDouble(value);
			}else if(type==float.class||type==Float.class){
				val = Float.parseFloat(value);
			}else if(type==byte.class||type==Byte.class){
				val = (byte)Integer.parseInt(value);
			}else if(type==char.class||type==Character.class){
				if(value.length() > 0){
					val = value.charAt(0);
				}else{
					val = '\0';
				}
				
			}else if(type==boolean.class||type==Boolean.class){
				val = "true".equals(value);
			}else if(type==StringBuilder.class){
				val = new StringBuilder(value);
			}else if(type==StringBuffer.class){
				val = new StringBuffer(value);
			}else if(type==BigDecimal.class){
				val = new BigDecimal(value);
			}else if(type==Date.class){
				val = new Date(Long.parseLong(value));
			}
			
			field.set(useObj, val);
		} catch (Exception e) {
			
		}
	}
	public Object getFieldObject(String name,Object useObj){
		if(useObj == null){
			return null;
		}
		try {
			Field field = useObj.getClass().getDeclaredField(name);
			field.setAccessible(true);
			Object obj = field.get(useObj);
			if(obj == null){
				obj = field.getType().newInstance();
				field.set(useObj, obj);
			}
			return obj;
		} catch (Exception e) {
			return null;
		}
	}

}
